import {
  BadGatewayException,
  ConflictException,
  HttpException,
  HttpStatus,
  Injectable,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { AES, HmacSHA512 } from 'crypto-js';
import { IdDto } from 'src/common/dto/id.dto';
import { ConfigService } from '@nestjs/config';
import { EmployeeEntity } from './employee.entity';
import { EmployeeInsertDto } from './dto/employee.insert.dto';
import { EmployeeSearchDto } from './dto/employee.search.dto';
import { EmployeeUpdateDto } from './dto/employee.update.dto';
import { CacheService } from 'src/cache/cache.service';
import { EmployeeSignDto } from './dto/employee.sign.dto';
import { EmployeeSignType } from './type/employee.sign.type';

@Injectable()
export class EmployeeService {
  constructor(
    @InjectRepository(EmployeeEntity)
    private readonly employeeRepository: Repository<EmployeeEntity>,
    private readonly configService: ConfigService,
    private readonly cacheService: CacheService,
  ) {}

  // 查询用户【根据query条件】
  find(querys: EmployeeSearchDto): Promise<EmployeeEntity[]> {
    return this.employeeRepository.find({ where: querys });
  }

  // 根据id查询
  async findOneById(id: number): Promise<EmployeeEntity> {
    try {
      const findUserById: EmployeeEntity =
        await this.employeeRepository.findOneBy({ id });
      if (!findUserById) {
        throw new HttpException(
          '当前用户id不存在数据库中',
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }
      return findUserById;
    } catch (error) {
      throw new HttpException(error.response, error.status);
    }
  }

  // 分页模糊查询
  async getManyAndCount(query: EmployeeSearchDto): Promise<any> {
    const data = {
      list: [],
      total: 0,
    };
    try {
      const list = await this.employeeRepository
        .createQueryBuilder('user')
        .where('user.account like :account')
        .andWhere('user.name like :name')
        .andWhere('user.phone like :phone')
        .andWhere('user.email like :email')
        .andWhere('user.status like :status')
        .setParameters({
          // 用户名
          name: `%${query.name ? query.name : ''}%`,
          // 电话
          phone: `%${query.phone ? query.phone : ''}%`,
          // 邮箱
          email: `%${query.email ? query.email : ''}%`,
          // 状态
          status: `%${query.status ? query.status : ''}%`,
        })
        .skip((query.page - 1) * query.pageSize)
        .take(query.pageSize)
        .getManyAndCount();
      data.list = list[0];
      data.total = list[1];
    } catch (error) {
      throw new HttpException('获取列表失败', 502);
    } finally {
      return data;
    }
  }

  // 新增
  async save(data: EmployeeInsertDto): Promise<boolean> {
    try {
      // 验证账号是否存在
      const findOneByAccount: EmployeeEntity =
        await this.employeeRepository.findOneBy({
          account: data.account,
        });
      if (findOneByAccount) {
        throw new ConflictException('账号已存在');
      }
      // 密码加密
      data.password = HmacSHA512(
        data.password,
        this.configService.get('TOKEN_KEY'),
      ).toString();
      // 保存用户信息
      const save: EmployeeEntity = await this.employeeRepository.save(data);
      if (!save) {
        throw new BadGatewayException('入库失败');
      }
      return true;
    } catch (error) {
      throw new HttpException(error.response, error.status);
    }
  }

  // 更新
  async updateById(data: EmployeeUpdateDto): Promise<boolean> {
    try {
      // 验证id是否存在
      const findOneById: EmployeeEntity =
        await this.employeeRepository.findOneBy({
          id: data.id,
        });
      if (!findOneById) {
        throw new HttpException('ID不存在', 400);
      }
      // 如果密码存在则对密码进行加密
      if (data.password) {
        data.password = HmacSHA512(
          data.password,
          this.configService.get('TOKEN_KEY'),
        ).toString();
      }
      // 更新用户信息
      const update = await this.employeeRepository.update(
        { id: data.id },
        data,
      );
      if (!update) {
        throw new HttpException('更新用户失败', 502);
      }
      return true;
    } catch (error) {
      throw new HttpException(error.response, error.status);
    }
  }

  // 删除
  async deleteById(data: IdDto): Promise<boolean> {
    try {
      // 删除用户信息
      const deleteById = await this.employeeRepository.delete(data);
      if (!deleteById) {
        throw new HttpException('删除用户失败', 502);
      }
      return true;
    } catch (error) {
      throw error;
    }
  }

  // 登陆
  async login(data: EmployeeSignDto): Promise<EmployeeSignType> {
    try {
      // 验证account是否存在
      const findOneByAccount = await this.employeeRepository.findOne({
        where: {
          account: data.account,
        },
      });
      if (!findOneByAccount) {
        throw new HttpException('账号不存在', 403);
      }
      // 验证用户名和密码是否匹配
      const _data = {
        account: data.account,
        password: HmacSHA512(
          data.password,
          this.configService.get('TOKEN_KEY'),
        ).toString(),
      };
      const findOne = await this.employeeRepository.findOne({
        where: _data,
      });
      if (!findOne) {
        throw new HttpException('密码错误', 403);
      }
      // 生成token
      const token = AES.encrypt(
        JSON.stringify({
          account: findOne.account,
          id: findOne.id,
        }),
        this.configService.get('TOKEN_KEY'),
      ).toString();
      // redis存储
      const setexRedis = await this.cacheService.set(
        findOne.account + ':token',
        token,
      );
      if (!setexRedis) {
        throw new HttpException('token存储redis失败', 500);
      }
      return { token, id: findOne.id };
    } catch (error) {
      throw new HttpException(error.response, error.status);
    }
  }

  // 注册
  async register(data: EmployeeSignDto): Promise<boolean> {
    try {
      // 验证账号是否存在
      const findOneByAccount: EmployeeEntity =
        await this.employeeRepository.findOneBy({
          account: data.account,
        });
      if (findOneByAccount) {
        throw new ConflictException('账号已存在');
      }
      // 密码加密
      data.password = HmacSHA512(
        data.password,
        this.configService.get('TOKEN_KEY'),
      ).toString();
      // 保存用户信息
      const save: EmployeeEntity = await this.employeeRepository.save(data);
      if (!save) {
        throw new BadGatewayException('入库失败');
      }
      // 返回值
      return !!save;
    } catch (error) {
      throw new HttpException(error.response, error.status);
    }
  }
}
